/******************************************************************************
 * 
 * Announce: CSharpKit, Basic algorithms, components and definitions.
 *           Copyright (C) ShenYongchen.
 *           All rights reserved.
 *   Author: 申永辰.郑州 (shenyczz@163.com)
 *  WebSite: http://github.com/shenyczz/CSharpKit
 *
 * THIS CODE IS LICENSED UNDER THE MIT LICENSE (MIT).
 * THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF 
 * ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
 * IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
 * PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
 * 
******************************************************************************/

using System;
using CSharpKit.Numerics.LinearAlgebra;

namespace CSharpKit.Numerics.LinearRegression
{
    /// <summary>
    /// 多元线性回归
    /// </summary>
    public static class MultipleRegression
    {
        /// <summary>
        /// Find the model parameters β such that X*β with predictor X becomes as close to response Y as possible, with least squares residuals.
        /// </summary>
        /// <param name="x">Predictor matrix X</param>
        /// <param name="y">Response vector Y</param>
        /// <param name="method">The direct method to be used to compute the regression.</param>
        /// <returns>Best fitting vector for model parameters β</returns>
        public static Vector<T> DirectMethod<T>(Matrix<T> x, Vector<T> y, DirectRegressionMethod method = DirectRegressionMethod.NormalEquations)
            where T : struct, IEquatable<T>, IFormattable
        {
            switch (method)
            {
                case DirectRegressionMethod.NormalEquations:
                   return NormalEquations(x, y);

                // case DirectRegressionMethod.QR:
                //    return QR(x, y);

                // case DirectRegressionMethod.Svd:
                //    return Svd(x, y);

                default:
                    throw new NotSupportedException(method.ToString());
            }
        }


        /// <summary>
        /// Find the model parameters β such that X*β with predictor X becomes as close to response Y as possible, with least squares residuals.
        /// Uses the cholesky decomposition of the normal equations.
        /// </summary>
        /// <param name="x">Predictor matrix X</param>
        /// <param name="y">Response vector Y</param>
        /// <returns>Best fitting vector for model parameters β</returns>
        public static Vector<T> NormalEquations<T>(Matrix<T> x, Vector<T> y) where T : struct, IEquatable<T>, IFormattable
        {
           if (x.RowCount != y.Count)
           {
               throw new ArgumentException(string.Format(Resources.Numerics.SampleVectorsSameLength, x.RowCount, y.Count));
           }

           if (x.ColumnCount > y.Count)
           {
               throw new ArgumentException(string.Format(Resources.Numerics.RegressionNotEnoughSamples, x.ColumnCount, y.Count));
           }

           return x.TransposeThisAndMultiply(x).Cholesky().Solve(x.TransposeThisAndMultiply(y));
        }




        //}}@@@
    }














}
